﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace uart_debugger
{
    class protokoll
    {
        private bool ascii;
        private bool checksumEn;
        private int function;
        private string adress;
        private int length;
        private string data;

        public protokoll()
        {

        }

        public protokoll(bool ascii,bool checksumEn, int function,string adress,int length,string data)
        {
            this.ascii = ascii;
            this.checksumEn = checksumEn;
            this.function = function;
            this.adress = adress;
            this.length = length;
            this.data = data;
        }


        public bool decodeRcvString(string rcvString)
        {
            bool result = true;
            int gesLaenge = 0;

            try
            {
            
                
                // ASCII oder Binär?
                if (rcvString.Substring(0, 1) == hexToString("01"))
                {
                    rcvString = rcvString.Remove(0, 1);

                }
                else if (rcvString.Substring(0, 1) == hexToString("3A"))
                {
                    rcvString = rcvString.Remove(0, 1);
                    // Wandeln in Binär
                    rcvString = asciiToBin(rcvString);
                }
                else
                {
                    result = false;
                }

                // Gesamtlänge berechnen
                gesLaenge = Convert.ToInt32("0x" + rcvString.Substring(0, 2), 16);
                
                // Checksumme enable (mit oder ohne?)
                if (rcvString.Substring(2, 1) == "0") checksumEn = false;
                else if (rcvString.Substring(2, 1) == "8") checksumEn = true;
                else result = false;

                // Funktionscode lesen
                if (rcvString.Substring(3, 1) == "1") function = 1;
                else if (rcvString.Substring(3, 1) == "2") function = 2;
                else if (rcvString.Substring(3, 1) == "3") function = 3;
                else result = false;

                // Abarbeitung je nach Funktionscode
                if (function == 1) // Comm-Test
                {
                    data = rcvString.Substring(4, 4);
                }
                else // Read oder Write
                {
                    adress = rcvString.Substring(4, 6);
                    length = Convert.ToInt32("0x" + rcvString.Substring(10, 2), 16);
                }

                // Wenn gelesen wurde
                if (function == 2)
                {
                    data = rcvString.Substring(12, length);
                }

            
            
            }
            catch (Exception ex)
            {
                result = false;
            }

            return result;
        }



        public string getUartString()
        {
            string s = "";

            // String zum Senden zusammenbauen
// Header ------------------------------------------------

            // Steuerzeichen /Funktionscode
                // no checksum      |  with checksum
                // -----------------------------------------
                // 01 Comm Test     |  81 Comm Test     
                // 02 Read   24bit  |  82 Read            
                // 03 Write  24bit  |  83 Write  

            if (checksumEn) s += "8";
            else s += "0";

            s += function.ToString();

// Daten -------------------------------------------------
            // Comm-Test
            if (function == 1)
            {
                s += "AA55";
            }
            // Read / Write
            else 
            {
                //Adresse
                s += adress;
                // Laenge
                s += length.ToString("X2");
                
                // Write
                if (function == 3)
                {
                    s += data;
                }
            }

// Länge berechnen (Gesamtnachricht ohne S)
            s = s.Insert(0, (s.Length + 2).ToString("X2"));

// Ascii/Binär Unterscheidung - ggf. ASCII umrechnung
            if (ascii)
            {
                // Länge ändern
                s = s.Remove(0, 2);
                s = s.Insert(0, ((s.Length + 2) * 2).ToString("X2"));

                // Jedes Zeichen in Ascii umwandeln
                s = hexToString("3A") + stringToAscii(s);

            }
            else // binär
            {
                s = s.Insert(0, hexToString("01"));
            }

// Chechsum ----------------------------------------------
            if (checksumEn)
            {
                int chksum = 0;
                char[] schar = s.ToCharArray();
                for (int i = 0; i < schar.Length; i++)
                {
                    chksum += schar[i];
                }

                chksum = chksum % 255;

                //Byte bitweise invertieren
                chksum = (byte)~chksum;

                chksum = Convert.ToInt32(chksum);
                chksum = chksum + 1;
                chksum = Convert.ToByte(chksum);
                

                if (ascii) s += stringToAscii(chksum.ToString("X").ToUpper());
                else s += chksum.ToString("X").ToUpper();
            }

            return s;
        }

// override string -----------------------------------------
        public override string ToString()
        {
            string s = "";
            if (function == 1) s += "Comm-Test";
            else if (function == 2) s += "Read";
            else if (function == 3) s += "Write";
            s += " / ";
            s += getUartString();
            s += " / ";
            s += data;
            return s;
        }

// StingOperationen ---------------------------------------
        private string hexToString(string hex)
        {
            return Convert.ToString((char)Convert.ToInt32("0x" + hex, 16));
        }

        private string charToHex(string ch)
        {
            string s = Convert.ToInt32(Convert.ToChar(ch)).ToString("x");
            return s;
        }

        private string stringToAscii(string s)
        {
            string sAscii = "";
            for (int i = 0; i < s.Length; i++)
            {
                sAscii += charToHex(s.Substring(i, 1));
            }
            return sAscii;
        }

        private string asciiToBin(string s)
        {
            string sBin = "";
            string substring = "";
            for (int i = 0; i < s.Length; i = i + 2)
            {
                substring = s.Substring(i, 2);
                sBin += hexToString(substring);
            }

            return sBin;
        }
    }
}
